//! ACID特性完整性测试
//! 
//! 本模块包含对事务系统ACID特性的全面测试，确保数据库的可靠性和一致性

use super::transaction::*;
use super::page::PageManager;
use super::tuple::RowId;
use std::sync::Arc;
use tempfile::tempdir;

/// ACID测试套件
/// 验证事务系统的原子性、一致性、隔离性和持久性
pub struct AcidTestSuite {
    transaction_manager: Arc<TransactionManager>,
    temp_dir: tempfile::TempDir,
}

impl AcidTestSuite {
    /// 创建新的ACID测试套件
    pub fn new() -> Result<Self, crate::Error> {
        let temp_dir = tempdir().map_err(|e| crate::Error::storage(format!("创建临时目录失败: {}", e)))?;
        let wal_path = temp_dir.path().join("acid_test.wal").to_string_lossy().to_string();
        let page_manager = Arc::new(PageManager::new(1000));
        
        let transaction_manager = Arc::new(TransactionManager::new(page_manager, wal_path)?);
        
        Ok(Self {
            transaction_manager,
            temp_dir,
        })
    }
    
    /// 测试原子性（Atomicity）
    /// 验证事务要么全部成功，要么全部失败
    pub fn test_atomicity(&self) -> Result<(), crate::Error> {
        println!("🧪 测试原子性（Atomicity）...");
        
        // 测试1: 正常提交的事务应该全部生效
        let tx1 = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
        
        // 模拟多个操作
        let mut write_set = tx1.write_set.write();
        write_set.insert(RowId { page_id: 1, slot_id: 1 });
        write_set.insert(RowId { page_id: 1, slot_id: 2 });
        write_set.insert(RowId { page_id: 1, slot_id: 3 });
        drop(write_set);
        
        // 提交事务
        self.transaction_manager.commit_transaction(tx1)?;
        
        // 验证事务已提交
        let stats = self.transaction_manager.get_stats();
        assert_eq!(stats.committed_transactions, 1);
        
        // 测试2: 回滚的事务应该完全撤销
        let tx2 = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
        
        // 模拟多个操作
        let mut write_set = tx2.write_set.write();
        write_set.insert(RowId { page_id: 1, slot_id: 4 });
        write_set.insert(RowId { page_id: 1, slot_id: 5 });
        write_set.insert(RowId { page_id: 1, slot_id: 6 });
        drop(write_set);
        
        // 回滚事务
        self.transaction_manager.rollback_transaction(tx2)?;
        
        // 验证事务已回滚
        let stats = self.transaction_manager.get_stats();
        assert_eq!(stats.rolled_back_transactions, 1);
        assert_eq!(stats.active_transactions, 0);
        
        println!("✅ 原子性测试通过");
        Ok(())
    }
    
    /// 测试一致性（Consistency）
    /// 验证事务执行前后数据库保持一致状态
    pub fn test_consistency(&self) -> Result<(), crate::Error> {
        println!("🧪 测试一致性（Consistency）...");
        
        // 测试场景：银行转账，总金额应该保持不变
        let initial_balance_a = 1000;
        let initial_balance_b = 500;
        let transfer_amount = 200;
        
        // 开始转账事务
        let tx = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
        
        // 模拟从账户A转账到账户B
        // 这里我们通过写集合来模拟数据变更
        let mut write_set = tx.write_set.write();
        write_set.insert(RowId { page_id: 2, slot_id: 100 }); // 账户A的行ID
        write_set.insert(RowId { page_id: 2, slot_id: 101 }); // 账户B的行ID
        drop(write_set);
        
        // 模拟业务逻辑验证
        let final_balance_a = initial_balance_a - transfer_amount;
        let final_balance_b = initial_balance_b + transfer_amount;
        let total_before = initial_balance_a + initial_balance_b;
        let total_after = final_balance_a + final_balance_b;
        
        // 验证总金额保持不变（一致性约束）
        assert_eq!(total_before, total_after);
        
        // 提交事务
        self.transaction_manager.commit_transaction(tx)?;
        
        println!("✅ 一致性测试通过");
        Ok(())
    }
    
    /// 测试隔离性（Isolation）
    /// 验证并发事务之间的隔离
    pub fn test_isolation(&self) -> Result<(), crate::Error> {
        println!("🧪 测试隔离性（Isolation）...");
        
        // 测试不同隔离级别
        self.test_read_uncommitted_isolation()?;
        self.test_read_committed_isolation()?;
        self.test_repeatable_read_isolation()?;
        self.test_serializable_isolation()?;
        
        println!("✅ 隔离性测试通过");
        Ok(())
    }
    
    /// 测试读未提交隔离级别
    fn test_read_uncommitted_isolation(&self) -> Result<(), crate::Error> {
        println!("  📋 测试读未提交隔离级别...");
        
        let tx1 = self.transaction_manager.begin_transaction(IsolationLevel::ReadUncommitted, false)?;
        let tx2 = self.transaction_manager.begin_transaction(IsolationLevel::ReadUncommitted, true)?;
        
        // tx1修改数据但未提交
        let mut write_set = tx1.write_set.write();
        write_set.insert(RowId::new(1, 200));
        drop(write_set);
        
        // tx2应该能读到未提交的数据（脏读）
        // 在读未提交级别下，这是允许的
        
        self.transaction_manager.rollback_transaction(tx1)?;
        self.transaction_manager.commit_transaction(tx2)?;
        
        Ok(())
    }
    
    /// 测试读已提交隔离级别
    fn test_read_committed_isolation(&self) -> Result<(), crate::Error> {
        println!("  📋 测试读已提交隔离级别...");
        
        let tx1 = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
        let tx2 = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, true)?;
        
        // tx1修改数据但未提交
        let mut write_set = tx1.write_set.write();
        write_set.insert(RowId::new(1, 201));
        drop(write_set);
        
        // tx2不应该读到未提交的数据
        // 验证快照时间戳
        assert!(tx2.snapshot_timestamp < tx1.id);
        
        self.transaction_manager.commit_transaction(tx1)?;
        self.transaction_manager.commit_transaction(tx2)?;
        
        Ok(())
    }
    
    /// 测试可重复读隔离级别
    fn test_repeatable_read_isolation(&self) -> Result<(), crate::Error> {
        println!("  📋 测试可重复读隔离级别...");
        
        let tx1 = self.transaction_manager.begin_transaction(IsolationLevel::RepeatableRead, true)?;
        let tx2 = self.transaction_manager.begin_transaction(IsolationLevel::RepeatableRead, false)?;
        
        // tx1读取数据
        let mut read_set = tx1.read_set.write();
        read_set.insert(RowId::new(1, 202));
        drop(read_set);

        // tx2修改同一数据并提交
        let mut write_set = tx2.write_set.write();
        write_set.insert(RowId::new(1, 202));
        drop(write_set);
        self.transaction_manager.commit_transaction(tx2)?;

        // tx1再次读取应该得到相同结果（可重复读）
        let read_set = tx1.read_set.read();
        assert!(read_set.contains(&RowId::new(1, 202)));
        drop(read_set);
        
        self.transaction_manager.commit_transaction(tx1)?;
        
        Ok(())
    }
    
    /// 测试串行化隔离级别
    fn test_serializable_isolation(&self) -> Result<(), crate::Error> {
        println!("  📋 测试串行化隔离级别...");
        
        let tx1 = self.transaction_manager.begin_transaction(IsolationLevel::Serializable, false)?;
        let tx2 = self.transaction_manager.begin_transaction(IsolationLevel::Serializable, false)?;
        
        // 模拟冲突操作
        let mut write_set1 = tx1.write_set.write();
        write_set1.insert(RowId::new(1, 203));
        drop(write_set1);

        let mut write_set2 = tx2.write_set.write();
        write_set2.insert(RowId::new(1, 203)); // 同一行
        drop(write_set2);
        
        // 在串行化级别下，应该检测到冲突
        self.transaction_manager.commit_transaction(tx1)?;
        
        // tx2应该被回滚或等待
        let result = self.transaction_manager.commit_transaction(tx2);
        // 根据实现，这里可能成功或失败
        
        Ok(())
    }
    
    /// 测试持久性（Durability）
    /// 验证已提交的事务在系统崩溃后仍然有效
    pub fn test_durability(&self) -> Result<(), crate::Error> {
        println!("🧪 测试持久性（Durability）...");
        
        // 创建并提交一个事务
        let tx = self.transaction_manager.begin_transaction(IsolationLevel::ReadCommitted, false)?;
        
        // 模拟数据变更
        let mut write_set = tx.write_set.write();
        write_set.insert(RowId::new(1, 300));
        write_set.insert(RowId::new(1, 301));
        drop(write_set);
        
        // 提交事务
        self.transaction_manager.commit_transaction(tx)?;
        
        // 强制刷新WAL以确保持久化
        self.transaction_manager.flush_wal()?;

        // 验证WAL中有记录
        let current_lsn = self.transaction_manager.get_current_lsn();
        assert!(current_lsn > 0);
        
        // 模拟系统重启（创建新的事务管理器）
        let wal_path = self.temp_dir.path().join("acid_test.wal").to_string_lossy().to_string();
        let page_manager = Arc::new(PageManager::new(1000));
        let new_tx_manager = TransactionManager::new(page_manager, wal_path)?;
        
        // 验证可以从WAL恢复
        // 这里我们检查WAL文件是否存在且有内容
        let new_lsn = new_tx_manager.get_current_lsn();
        assert!(new_lsn >= current_lsn);
        
        println!("✅ 持久性测试通过");
        Ok(())
    }
    
    /// 运行完整的ACID测试套件
    pub fn run_full_test_suite(&self) -> Result<(), crate::Error> {
        println!("🚀 开始ACID完整性测试套件...");
        println!("=====================================");
        
        self.test_atomicity()?;
        self.test_consistency()?;
        self.test_isolation()?;
        self.test_durability()?;
        
        println!("=====================================");
        println!("🎉 ACID测试套件全部通过！");
        
        // 输出统计信息
        let stats = self.transaction_manager.get_stats();
        println!("📊 测试统计:");
        println!("  总事务数: {}", stats.total_transactions);
        println!("  已提交事务: {}", stats.committed_transactions);
        println!("  已回滚事务: {}", stats.rolled_back_transactions);
        println!("  活跃事务: {}", stats.active_transactions);
        
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_acid_atomicity() {
        let test_suite = AcidTestSuite::new().unwrap();
        test_suite.test_atomicity().unwrap();
    }
    
    #[test]
    fn test_acid_consistency() {
        let test_suite = AcidTestSuite::new().unwrap();
        test_suite.test_consistency().unwrap();
    }
    
    #[test]
    fn test_acid_isolation() {
        let test_suite = AcidTestSuite::new().unwrap();
        test_suite.test_isolation().unwrap();
    }
    
    #[test]
    fn test_acid_durability() {
        let test_suite = AcidTestSuite::new().unwrap();
        test_suite.test_durability().unwrap();
    }
    
    #[test]
    fn test_full_acid_suite() {
        let test_suite = AcidTestSuite::new().unwrap();
        test_suite.run_full_test_suite().unwrap();
    }
}
